#include "ch32l103.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesTime.h"
#include "DevicesDelay.h"
#include "DevicesQueue.h"
#include "DriverPD.h"


/* PD接口 */
PdType g_typePD;

/* USB PD DMA 需要4字节对齐 */
__attribute__ ((aligned(4))) PdMessStdType g_typePDMessTx, g_typePDMessRx;

const PdCapabiType g_typeSrcCapabi[5] =
{
    {.sinkFixed = {.type = 0, .voltage = 5000  / 50, .maxCurrent = 500 / 10, .dualRolePower = 0, .dualRoleData = 0, .fastRoleSwap = 0}},
    {.sinkFixed = {.type = 0, .voltage = 9000  / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 12000 / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 15000 / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 20000 / 50, .maxCurrent = 500 / 10}},
};

const PdCapabiType g_typeSinkCapabi[5] =
{
    {.sinkFixed = {.type = 0, .voltage = 5000  / 50, .maxCurrent = 500 / 10, .dualRolePower = 0, .dualRoleData = 0, .fastRoleSwap = 0}},
    {.sinkFixed = {.type = 0, .voltage = 9000  / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 12000 / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 15000 / 50, .maxCurrent = 500 / 10}},
    {.sinkFixed = {.type = 0, .voltage = 20000 / 50, .maxCurrent = 500 / 10}},
};

/* ms */
uint32_t uiPdTimeGet(void)
{
    return lTimebaseGet() / 1000LL;
}

void USBPD_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USBPD_IRQHandler(void)
{
    /* 接收完成中断标志 */
    if(USBPD->STATUS & IF_RX_ACT)
    {
        /* 清除接收完成中断标志 */
        USBPD->STATUS |= IF_RX_ACT;

        /* SOP0 是发给设备的、SOP' 和 SOP'' 是发给线材的 */
        if((USBPD->STATUS & MASK_PD_STAT) == PD_RX_SOP0)
        {
            /* 协议规定，数据长度为：2 - 30 Byte */
            if(USBPD->BMC_BYTE_CNT > 1)
            {
                /* 如果不是接收到GoodCRC，则需要回复GoodCRC */
                if(!((g_typePDMessRx.head.type == DEF_TYPE_GOODCRC) && (g_typePDMessRx.head.number == 0) && (g_typePDMessRx.head.extended == 0)))
                {
                    enumQueuePushDatas(&g_TypeQueueUsbPdRead, &g_typePDMessRx, sizeof(g_typePDMessRx));

                    /* 及时回复 GoodCRC */
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_GOODCRC, g_typePDMessRx.head.ID);
                }
            }
        }
    }

    /* 接收复位中断标志 */
    if(USBPD->STATUS & IF_RX_RESET)
    {
        /* 清除复位中断标志 */
        USBPD->STATUS |= IF_RX_RESET;
    }

    /* 发送完成中断标志 */
    if(USBPD->STATUS & IF_TX_END)
    {
        /* 清除发送完成中断标志  */
        USBPD->STATUS |= IF_TX_END;

        cPdRxMode();
    }
}

int8_t cPdInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOB, ENABLE);
    RCC_HBPeriphClockCmd(RCC_HBPeriph_USBPD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = PIN_CC1 | PIN_CC2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* 配置 USB PD CC 引脚模式 */
    AFIO->CR |= USBPD_IN_HVT;

    /* 设置 CC线 以正常VDD电压驱动输出 */
    USBPD->PORT_CC1 &= ~CC_LVE;
    USBPD->PORT_CC2 &= ~CC_LVE;

    /* 清除全部状态 */
    USBPD->STATUS = BUF_ERR | IF_RX_BIT | IF_RX_BYTE | IF_RX_ACT | IF_RX_RESET | IF_TX_END;

    /* 开启发送完成中断、接收完成中断、接收复位中断 */
    USBPD->CONFIG = IE_TX_END | IE_RX_ACT | IE_RX_RESET | PD_DMA_EN;

    g_typePD.version = 1;

    cPdSinkInit();

    cPdRxMode();

    NVIC_InitStructure.NVIC_IRQChannel = USBPD_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return 0;
}

int8_t cPdDeinit(void)
{
    return 0;
}

int8_t cPdSrcInit(void)
{
    USBPD->PORT_CC1 = CC_CMP_66 | CC_PU_330;
    USBPD->PORT_CC2 = CC_CMP_66 | CC_PU_330;

    g_typePD.PortPowerRole = 1;
    g_typePD.PortDataRole = 1;

    return 0;
}

int8_t cPdSinkInit(void)
{
    USBPD->PORT_CC1 = CC_CMP_66 | CC_PD;
    USBPD->PORT_CC2 = CC_CMP_66 | CC_PD;

    g_typePD.PortPowerRole = 0;
    g_typePD.PortDataRole = 0;

    return 0;
}

/* 配置 CC 通道 */
void vPdCCSet(uint8_t ucChannel)
{
    /* 选择对应的 CC 端口通讯 */
    (ucChannel & 0x01) ? (USBPD->CONFIG &= ~CC_SEL) : (USBPD->CONFIG |= CC_SEL);

    g_typePD.connected = ucChannel;

    /* 等待源端发送 电源参数 列表 */
    g_typePD.timeout = uiPdTimeGet();
    g_typePD.status = STA_SRC_CONNECT;
}

uint8_t ucPdCCDetect(void)
{
    static uint8_t ucFlag = 0;

    if(ucFlag != 0)
        return ucFlag;

    if(g_typePD.connected == 0)
    {
        /* 先测试 CC1 有没有被上、下拉 */
        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_22;
        vDelayUs(2);
        ucFlag |= (USBPD->PORT_CC1 & PA_CC_AI) ? 0x01 : 0;
        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_66;

        /* 再测试 CC2 有没有被上、下拉 */
        USBPD->PORT_CC2 = (USBPD->PORT_CC2 & ~(CC_CE | PA_CC_AI)) | CC_CMP_22;
        vDelayUs(2);
        ucFlag |= (USBPD->PORT_CC2 & PA_CC_AI) ? 0x10 : 0;
        USBPD->PORT_CC2 = (USBPD->PORT_CC2 & ~(CC_CE | PA_CC_AI)) | CC_CMP_66;
    }
    else
    {
//        /* 先测试 CC1 有没有被上、下拉 */
//        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_22;
//        vDelayUs(2);
//        ucFlag |= (USBPD->PORT_CC1 & PA_CC_AI) ? 0x01 : 0;
//
//        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_66;
//        vDelayUs(2);
//        ucFlag |= (USBPD->PORT_CC1 & PA_CC_AI) ? 0x02 : 0;
//
//        ucFlag |= (GPIO_ReadInputDataBit(GPIOC, PIN_CC1) != 0) ? 0x04 : 0;
//
//
//        /* 再测试 CC2 有没有被上、下拉 */
//        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_22;
//        vDelayUs(2);
//        ucFlag |= (USBPD->PORT_CC1 & PA_CC_AI) ? 0x10 : 0;
//
//        USBPD->PORT_CC1 = (USBPD->PORT_CC1 & ~(CC_CE | PA_CC_AI)) | CC_CMP_66;
//        vDelayUs(2);
//        ucFlag |= (USBPD->PORT_CC1 & PA_CC_AI) ? 0x20 : 0;
//
//        ucFlag |= (GPIO_ReadInputDataBit(GPIOC, PIN_CC1) != 0) ? 0x40 : 0;
    }

    /* SINK */
    if(USBPD->PORT_CC1 & CC_PD)
    {

    }
    /* SRC */
    else
    {

    }

    /* 配置 CC 通道 */
    vPdCCSet(ucFlag);

    if(ucFlag != 0)
    {
        printf("ucPdCCDetect: 0x%02X\r\n", ucFlag);
    }

    return ucFlag;
}

int8_t cPdRxMode(void)
{
    /* 清除全部状态 */
    USBPD->CONFIG  |=  PD_ALL_CLR;
    USBPD->CONFIG  &= ~PD_ALL_CLR;

    USBPD->BMC_CLK_CNT = UPD_TMR_RX_96M;
    USBPD->DMA      = (uint32_t)&g_typePDMessRx;
    /* 设置为接收模式 */
    USBPD->CONTROL &= ~PD_TX_EN;
    /* 开始接收 */
    USBPD->CONTROL |= BMC_START;

    return 0;
}

static int8_t cPdDatasSend(uint8_t ucSop, void *pvDatas, int32_t iLength)
{
    /* 只有当发送指针为NULL，但发送长度又不为0时，才是错误状态 */
    if((pvDatas == NULL) && (iLength > 0))
        return 1;

//    uint8_t *pucDatas = pvDatas;
//    int32_t i = 0;

//    printf("cPdDatasSend %d: ", ucSop);
//    for(i = 0; i < iLength; ++i)
//    {
//        printf(" %02X", *pucDatas++);
//    }
//    printf("\r\n");

    USBPD->BMC_CLK_CNT  = UPD_TMR_TX_96M;
    USBPD->TX_SEL       = ucSop;
    USBPD->DMA          = (uint32_t)pvDatas;
    USBPD->BMC_TX_SZ    = iLength;

    /* 清除发送完成状态 */
    USBPD->STATUS      |= IF_TX_END;
    /* 发送使能 */
    USBPD->CONTROL     |= PD_TX_EN;
    /* 开始发送 */
    USBPD->CONTROL     |= BMC_START;

    /* 等待发送完成 （发送完成中断，会设置为接收模式）*/
    while(((USBPD->STATUS & IF_TX_END) == 0) && (USBPD->CONTROL & PD_TX_EN));

    return 0;
}

int8_t cPdMessHeadLoad(void *pvHead, uint8_t ucEx, uint8_t ucType, uint8_t ucID, uint8_t ucLength)
{
    PdMessHeadType *ptypeMessHead = (PdMessHeadType *)pvHead;

    if(pvHead == NULL)
        return 1;

    ptypeMessHead->extended         = ucEx;
    ptypeMessHead->number           = ucLength >> 2;
    ptypeMessHead->ID               = ucID;
    ptypeMessHead->PortPowerRole    = g_typePD.PortPowerRole;
    ptypeMessHead->version          = g_typePD.version;
    ptypeMessHead->PortDataRole     = g_typePD.PortDataRole;
    ptypeMessHead->type             = ucType;

    return 0;
}

/* 利用CC发送一帧数据 */
int8_t cPdPackSend(uint8_t ucSop, uint8_t ucEx, uint8_t ucType, uint8_t ucID, void *pvDatas, int32_t iDataLength, int8_t cWaitCnt)
{
    PdMessStdType *ptypePdMess = &g_typePDMessTx;
    int8_t cTimeout;

    /* 加载消息头 */
    cPdMessHeadLoad(&ptypePdMess->head, ucEx, ucType, ucID, iDataLength);

    /* 加载消息数据 */
    memcpy(ptypePdMess->datas, pvDatas, iDataLength);

    /* 协议规定最多发送 3 次，直到收到 GoodCRC */
    do
    {
        g_typePDMessRx.head.type = 0;

        /* 发送消息 */
        cPdDatasSend(ucSop, ptypePdMess, 2 + iDataLength);

        /* 协议规定等待超时（0.9~1.1ms) */
        for(cTimeout = 100; (g_typePDMessRx.head.type != DEF_TYPE_GOODCRC) && cWaitCnt && cTimeout; --cTimeout)
        {
            vDelayUs(10);
        }
    }
    while(((--cWaitCnt) > 0) && (cTimeout <= 0));

    return 0;
}

/* 请求第x个电源 */
int8_t cPdRequest(uint8_t ucIndex)
{
    PdRequestCapabiType typeRequestCapabi = {0};

    typeRequestCapabi.objectPosition    = ucIndex + 1;
    /* 请求需要的电流大小 */
    typeRequestCapabi.operatCurrent     = g_typePD.srcCapabi[ucIndex].fixed.maxCurrent;
    typeRequestCapabi.maxCurrent        = g_typePD.srcCapabi[ucIndex].fixed.maxCurrent;

    return cPdPackDatasSend(UPD_SOP0, DEF_TYPE_REQUEST, ++g_typePDMessTx.head.ID, &typeRequestCapabi, sizeof(typeRequestCapabi));
}

int8_t cPdCapabilitesAna(PdType *ptypePd)
{
    uint32_t voltageMax, voltageMin, currentMax, powerMax;
    uint8_t i;

    for(i = 0; i < ptypePd->srcCapabNum; ++i)
    {
        if(ptypePd->srcCapabi[i].fixed.type == 0)
        {
            voltageMin = ptypePd->srcCapabi[i].fixed.voltage * 50;
            currentMax = ptypePd->srcCapabi[i].fixed.maxCurrent * 10;

            printf("PDO %d fixed voltage: %d \t currentMax: %d\r\n", i, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].fixed.type == 1)
        {
            voltageMax = ptypePd->srcCapabi[i].battery.maxVoltage * 50;
            voltageMin = ptypePd->srcCapabi[i].battery.minVoltage * 50;
            powerMax   = ptypePd->srcCapabi[i].battery.maxPower * 250;

            printf("PDO %d battery voltageMax: %d \t voltageMin: %d \t powerMax: %d\r\n", i, voltageMax, voltageMin, powerMax);
        }
        else if(ptypePd->srcCapabi[i].fixed.type == 2)
        {
            voltageMax = ptypePd->srcCapabi[i].variable.maxVoltage * 50;
            voltageMin = ptypePd->srcCapabi[i].variable.minVoltage * 50;
            currentMax = ptypePd->srcCapabi[i].variable.maxCurrent * 10;

            printf("PDO %d variable voltageMax: %d \t voltageMin: %d \t currentMax: %d\r\n", i, voltageMax, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 0)
        {
            voltageMax = ptypePd->srcCapabi[i].sprProgram.maxVoltage * 100;
            voltageMin = ptypePd->srcCapabi[i].sprProgram.minVoltage * 100;
            currentMax = ptypePd->srcCapabi[i].sprProgram.maxCurrent * 50;

            printf("PDO %d Program voltageMax: %d \t voltageMin: %d \t currentMax: %d\r\n", i, voltageMax, voltageMin, currentMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 1)
        {
            voltageMax = ptypePd->srcCapabi[i].eprAdjus.maxVoltage * 100;
            voltageMin = ptypePd->srcCapabi[i].eprAdjus.minVoltage * 100;
            powerMax   = ptypePd->srcCapabi[i].eprAdjus.inctements * 50;

            printf("PDO %d EPR voltageMax: %d \t voltageMin: %d \t powerMax: %d\r\n", i, voltageMax, voltageMin, powerMax);
        }
        else if(ptypePd->srcCapabi[i].sprProgram.APDO == 2)
        {
            printf("PDO %d SPR\r\n", i);
        }
        else
        {
            printf("SPR error.\r\n");
        }
    }

    return 0;
}

int8_t cPdMessRecive(PdMessStdType *ptypePdMess)
{
    PdType *ptypePd = &g_typePD;

    if(ptypePdMess == NULL)
        return 1;

//    int8_t i;
//    printf("cPdMessRecive:\r\n");
//    printf("head: %d, %d, %d, %d, %d, %d, %d\r\n",
//             ptypePdMess->head.extended,
//             ptypePdMess->head.number,
//             ptypePdMess->head.ID,
//             ptypePdMess->head.PortPowerRole,
//             ptypePdMess->head.version,
//             ptypePdMess->head.PortDataRole,
//             ptypePdMess->head.type);
//    printf("data:");
//    for(i = 0; i < ptypePdMess->head.number; ++i)
//    {
//        printf(" %08X", ptypePdMess->datas[i]);
//    }
//    printf("\r\n");

    /* 非拓展消息 */
    if(ptypePdMess->head.extended == 0)
    {
        /* 控制消息 */
        if(ptypePdMess->head.number == 0)
        {
            switch(ptypePdMess->head.type)
            {
                /* GotoMin消息只适用于那些在接收请求数据对象。它是对接收端口的一个指令，将其操作功率级别降低到最小. */
                case DEF_TYPE_GOTOMIN:
                    printf("DEF_TYPE_GOTOMIN\r\n");
                    break;

                /* 在这些情况下，接受讯息是有效的回应: Request、PR_Swap、DR_Swap、VCONN_Swap、FR_Swap、Soft_Reset */
                case DEF_TYPE_ACCEPT:
                    printf("DEF_TYPE_ACCEPT\r\n");
                    ptypePd->timeout = uiPdTimeGet();
                    ptypePd->status = (ptypePd->status == STA_RX_ACCEPT_WAIT) ? STA_RX_PS_RDY_WAIT : STA_IDLE;
                    break;

                    /* 在这些情况下，接受讯息是有效的回应: Request、PR_Swap、DR_Swap、VCONN_Swap */
                case DEF_TYPE_REJECT:
                    printf("DEF_TYPE_REJECT\r\n");
                    break;

                    /* 由源发送表示电源已达到所需的工作状态 */
                case DEF_TYPE_PS_RDY:
                    printf("DEF_TYPE_PS_RDY\r\n");
                    ptypePd->status = STA_IDLE;
                    break;

                    /* 得到源端功能，对方回应Source_Capabilities Message */
                case DEF_TYPE_GET_SRC_CAP:
                    printf("DEF_TYPE_GET_SRC_CAP\r\n");
                    cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SNK_CAP, ++g_typePDMessTx.head.ID, (void *)&g_typeSrcCapabi, sizeof(g_typeSrcCapabi));
                    break;

                    /* 得到Sink端功能，对方回应Sink_Capabilities Message */
                case DEF_TYPE_GET_SNK_CAP:
                    printf("DEF_TYPE_GET_SNK_CAP\r\n");
                    cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SNK_CAP, ++g_typePDMessTx.head.ID, (void *)&g_typeSinkCapabi, sizeof(g_typeSinkCapabi));
                    break;

                    /* DR_Swap消息的接收者应通过发送Accept消息、Reject消息或Wait消息来响应。接收到Accept后，DFP，UFP交换角色。Reject不采取措施。Wait表示将来可能交换，暂时不采取操作 */
                case DEF_TYPE_DR_SWAP:
                    printf("DEF_TYPE_DR_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, ++g_typePDMessTx.head.ID);
                    break;

                    /* 任何端口合作伙伴都可以发送PR_Swap消息来请求交换电源角色。返回消息为Accept消息、Reject消息或Wait */
                case DEF_TYPE_PR_SWAP:
                    printf("DEF_TYPE_PR_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, ++g_typePDMessTx.head.ID);
                    break;

                    /* 交换VCONN角色。消息发送后，对方执行。新的V CONN源将发送PS_RDY消息，指示它现在正在寻找VCONN。初始V CONN源在收到PS_RDY消息的最后一位EOP后，应停止在tVCONNSourceOff内寻找VCONN */
                case DEF_TYPE_VCONN_SWAP:
                    printf("DEF_TYPE_VCONN_SWAP\r\n");
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, ++g_typePDMessTx.head.ID);
                    break;

                    /* 回复对方的请求，让对方稍等再进行请求 */
                case DEF_TYPE_WAIT:
                    printf("DEF_TYPE_WAIT\r\n");
                    break;

                /* 当存在消息同步错误时，源或接收器可以发送一条Soft_Reset消息。软t_reset消息从协议层错误中恢复。接收放会恢复到PE_SNK_Ready和PE_SRC_Ready状态 */
                case DEF_TYPE_SOFT_RESET:
                    printf("DEF_TYPE_SOFT_RESET\r\n");
                    cPdDeinit();
                    cPdPackControlSend(UPD_SOP0, DEF_TYPE_ACCEPT, ++g_typePDMessTx.head.ID);
                    break;

                    /* 数据复位 */
                case DEF_TYPE_DATA_RESET:
                    printf("DEF_TYPE_DATA_RESET\r\n");
                    break;

                    /* 数据复位完成 */
                case DEF_TYPE_DATA_RESET_CMP:
                    printf("DEF_TYPE_DATA_RESET_CMP\r\n");
                    break;

                    /* 不支持对方发送的请求 */
                case DEF_TYPE_NOT_SUPPORT:
                    printf("DEF_TYPE_NOT_SUPPORT\r\n");
                    break;

                    /* 请求关于端口源功能的附加信息 */
                case DEF_TYPE_GET_SRC_CAP_EX:
                    printf("DEF_TYPE_GET_SRC_CAP_EX\r\n");
                    break;

                    /* 请求端口合作伙伴的当前状态。源或接收器应返回一条状态消息作为响应 */
                case DEF_TYPE_GET_STATUS:
                    printf("DEF_TYPE_GET_STATUS\r\n");
                    break;

                    /* 接收器发送Get_PPS_Status消息来请求关于源状态的附加信息 */
                case DEF_TYPE_GET_PPS_STATUS:
                    printf("DEF_TYPE_GET_PPS_STATUS\r\n");
                    break;

                    /* 支持的[ISO 3166]中定义的alpha-2国家代码 */
                case DEF_TYPE_GET_CTY_CODES:
                    printf("DEF_TYPE_GET_CTY_CODES\r\n");
                    break;

                default : break;
            }
        }
        /* 数据消息 */
        else
        {
            switch(ptypePdMess->head.type)
            {
                /* 供电方的供电能力信息 */
                case DEF_TYPE_SRC_CAP:
                    printf("DEF_TYPE_SRC_CAP\r\n");
                    memcpy(ptypePd->srcCapabi, ptypePdMess->datas, ptypePdMess->head.number * 4);
                    ptypePd->srcCapabNum = ptypePdMess->head.number;

                    /* 解析接收到的 电源端 列表 */
                    cPdCapabilitesAna(ptypePd);

                    ptypePd->status = STA_TX_REQ;
                    break;

                case DEF_TYPE_VENDOR_DEFINED:
                    printf("DEF_TYPE_VENDOR_DEFINED\r\n");
                    break;

                default : break;
            }
        }
    }
    /* 拓展消息 */
    else
    {

    }

    return 0;
}

int8_t cPdPoll(void)
{
    PdType *ptypePd = &g_typePD;
    PdMessStdType typePDMess;
    int8_t cError = 0;

    /* 检测CC引脚 */
    ucPdCCDetect();

    /* 读取并解析 USB CC 发送过来的数据 */
    while(iQueueGetLengthOfOccupy(&g_TypeQueueUsbPdRead) >= sizeof(PdMessStdType))
    {
        enumQueuePopDatas(&g_TypeQueueUsbPdRead, &typePDMess, sizeof(PdMessStdType));

        cPdMessRecive(&typePDMess);
    }

    /* 执行状态机 */
    switch(ptypePd->status)
    {
        case STA_IDLE :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_IDLE\r\n") : (void)0;
            break;

        case STA_SRC_CONNECT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_SRC_CONNECT\r\n") : (void)0;
            ptypePd->status = STA_RX_SRC_CAP_WAIT;
            break;

        case STA_RX_SRC_CAP_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_SRC_CAP_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_TX_REQ :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_REQ\r\n") : (void)0;
            /* 请求第x个电源 */
            cError = cPdRequest(0);
            ptypePd->timeout = (cError == 0) ? uiPdTimeGet() : 0;
            ptypePd->status  = (cError == 0) ? STA_RX_ACCEPT_WAIT : STA_IDLE;
            break;

        case STA_RX_ACCEPT_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_ACCEPT_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_RX_PS_RDY_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_PS_RDY_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_RX_REQ_WAIT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_RX_REQ_WAIT\r\n") : (void)0;
            if((uiPdTimeGet() - ptypePd->timeout) > 3000)
                ptypePd->status = STA_TX_HRST;
            break;

        case STA_TX_SRC_CAP :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_SRC_CAP\r\n") : (void)0;
            cError = cPdPackDatasSend(UPD_SOP0, DEF_TYPE_SNK_CAP, ++g_typePDMessTx.head.ID, (void *)&g_typeSrcCapabi, sizeof(g_typeSrcCapabi));
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_ACCEPT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_ACCEPT\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_ACCEPT, ++g_typePDMessTx.head.ID);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_REJECT :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_REJECT\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_REJECT, ++g_typePDMessTx.head.ID);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_PS_RDY :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_PS_RDY\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_PS_RDY, ++g_typePDMessTx.head.ID);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_SOFTRST :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_SOFTRST\r\n") : (void)0;
            cError = cPdPackControlSend(UPD_SOP0, DEF_TYPE_SOFT_RESET, ++g_typePDMessTx.head.ID);
            ptypePd->status = STA_IDLE;
            break;

        case STA_TX_HRST :
            (ptypePd->statusLast != ptypePd->status) ? ptypePd->statusLast = ptypePd->status, printf("STA_TX_HRST\r\n") : (void)0;
            cError = cPdDatasSend(UPD_HARD_RESET, NULL, 0);
            ptypePd->timeout = uiPdTimeGet();
            ptypePd->status = STA_RX_SRC_CAP_WAIT;
            break;

        default : cError = 1; break;
    }

    return cError;
}
